import Konva from "konva";
import { Draw } from "../Draw/Draw";
import { HISTORY_MAX_RECORED } from "../Config";

export class HistoryManager {
  private draw: Draw;
  private undoStack: Konva.Layer[] = []; // undo 栈
  private redoStack: Konva.Layer[] = []; // redo 栈

  constructor(draw: Draw) {
    this.draw = draw;
  }

  // 撤销动作
  public undo() {
    // 需要保留背景图层，因此 撤销栈不能为0
    if (this.undoStack.length <= 1) return console.log("不可撤销");

    // 获取当前图层，放到 redoStack，并删除 undoStack
    const layer = this.undoStack.pop()!;
    this.redoStack.push(layer);

    // 重新渲染图层
    this.render();
  }

  // 重做动作
  public redo() {
    if (this.redoStack.length <= 0) return console.log("不可重做");

    // 获取当前图层，放到 undoStack，并删除 redoStack
    const layer = this.redoStack.pop()!.clone();
    this.undoStack.push(layer.clone());

    // 重新渲染图层
    this.render();
  }

  /** 添加记录 */
  public patchHistory() {
    const layer = this.draw.getLayer();
    if (!layer) return;

    const layerClone = layer.clone();
    // 当前图层的JSON串 - 不直接使用 toJSON()，避免后续修改
    const layerJson = JSON.stringify(layerClone.toObject());

    // 被添加图层与最后缓存的记录是否一致
    const lastLayer = this.undoStack[this.undoStack.length - 1];
    const lastLayerJson = JSON.stringify(lastLayer?.toObject());

    if (layerJson === lastLayerJson) return;

    layerClone.find("Transformer").forEach((tr) => tr.destroy());

    // 不然直接添加到 undoStack
    this.undoStack.push(layerClone);

    // 如果记录数大于 HISTORY_MAX_RECORED，则删除最前的记录
    while (this.undoStack.length > HISTORY_MAX_RECORED) this.undoStack.shift();
  }

  // 清空历史记录
  public clearHistory() {
    this.undoStack = [];
    this.redoStack = [];
  }

  /** 重新渲染图层 */
  private render() {
    // 取出上一次的图层，并添加到当前图层
    const lastLayer = this.undoStack[this.undoStack.length - 1];
    const layerClone = lastLayer.clone(); // 这里一定要 clone 避免图层引用导致的历史记录异常问题

    // 进行图层更新
    this.draw.clearLayer(); // 删除layer
    this.draw.setLayer(layerClone); // 修正 layer
    this.draw.getStage().add(layerClone);
    this.draw.render({ patchHistory: false });
  }
}
